package datastruct.lineList;

/**
 * 动态数组
 *
 * @author RunningShrimp
 * @date 2021/5/8  21:45
 */
@SuppressWarnings("unchecked")
public class Array<E> implements LineList<E> {
    /**
     * 元素的数量
     */
    private int size;
    /**
     * 存储的数组
     */
    private E[] elementData;

    public Array(int capacity) {
        this.size = 0;
        elementData = (E[]) new Object[capacity];
    }

    public Array() {
        this(10);
    }

    public Array(E[] array) {
        elementData = (E[]) new Object[array.length];
        System.arraycopy(array, 0, elementData, 0, array.length);
        size = elementData.length;
    }

    @Override
    public boolean add(E e, int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("索引无效");
        }
        if (size == elementData.length) {
            resize(elementData.length * 2);
        }
        if (size - index >= 0) {
            System.arraycopy(elementData, index, elementData, index + 1, size - index);
        }
        elementData[index] = e;
        size++;
        return true;
    }

    @Override
    public boolean add(E e) {
        return add(e, size);
    }

    public boolean addLast(E e) {
        return add(e, size);
    }

    @Override
    public E remove(E e) {
        int index = find(e);
        if (index > -1) {
            remove(index);
        }
        return null;
    }

    @Override
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("索引无效");
        }
        E e = elementData[index];
        if (size - (index + 1) >= 0) {
            System.arraycopy(elementData, index + 1, elementData, index + 1 - 1, size - (index + 1));
        }
        size--;
        elementData[size] = null;
        return e;
    }

    public E removeLast() {
        return remove(size - 1);
    }

    public E removeFirst() {
        return remove(0);
    }

    @Override
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("索引无效");
        }
        return elementData[index];
    }

    public E getLast() {
        return get(size - 1);
    }

    public E getFirst() {
        return get(0);
    }

    @Override
    public boolean set(E e, int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("索引无效");
        }
        elementData[index] = e;
        return true;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean contains(E e) {
        for (int i = 0; i < size; i++) {
            if (elementData[i].equals(e)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (elementData[i].equals(e)) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public boolean clear() {
        elementData = (E[]) new Object[10];
        size = 0;
        return true;
    }

    @Override
    public int size() {
        return size;
    }

    public void swap(int i, int j) {
        if (i < 0 || i >= size || j < 0 || j >= size) {
            throw new IllegalArgumentException("索引无效");
        }
        E e = elementData[i];
        elementData[i] = elementData[j];
        elementData[j] = e;
    }

    /**
     * 将数组空间的容量变成newCapacity大小
     *
     * @param newCapacity 信容量大小
     */

    private void resize(int newCapacity) {

        E[] newData = (E[]) new Object[newCapacity];
        if (size >= 0) {
            System.arraycopy(elementData, 0, newData, 0, size);
        }
        elementData = newData;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder().append("Array's size is ").append(size).append(" , element is [");
        for (int i = 0; i < size; i++) {
            stringBuilder.append(elementData[i]);
            if (i != size - 1) {
                stringBuilder.append(" , ");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}
